#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

#include "util.h"

/*
 * @return timestamp in millisecond
 */
double getTimeStamp() {
   struct timeval tv;
   struct timezone tz;
   double t;

   gettimeofday(&tv,&tz);
   t = ((double) tv.tv_sec)*1000 + tv.tv_usec/1000;
   return t;
}

/*
 * Read a matrix from raw file
 * @param filename The input file name (input)
 * @param padding_size Padding the number of rows to multiple of padding_size (input)
 * @param row Number of rows (intput)
 * @param col Number of columns (input)
 * @param padded_row Number of padded rows (output) 
 * @return An array representing a matrix. The array should be freed after used.
 */
float * read_raw_matrix(char *filename, int padding_size, int row, int col, int *padded_row) {
   float *M;
   int size, nmemb;
   FILE *fin;

   nmemb = row*col;
   *padded_row = ((row + padding_size - 1)/padding_size)*padding_size;
   M = (float *) malloc((*padded_row)*col*sizeof(float));
  
   if ((fin = fopen(filename,"r")) == NULL) {
      fprintf(stderr,"Cannot open file %s\n",filename);
      exit(1);
   }
   size = fread(M,sizeof(float),nmemb,fin);
   if (size != nmemb) {
      fprintf(stderr,"Input file %s too short\n",filename);
      exit(1);
   }
   fclose(fin);
   return M;
}

/*
 * Read a matrix from filename
 * @param filename The input file name (input)
 * @param padding_size Padding the number of rows to multiple of padding_size (input)
 * @param row Number of rows (output)
 * @param col Number of columns (output)
 * @param padded_row Number of padded rows (output) 
 * @return An array representing a matrix. The array should be freed after used.
 */
float* read_matrix(char *filename, int padding_size, int *row, int *col,int *padded_row) {
   FILE *fi;
   char *line, *word, *str;
   size_t bufsize;
   ssize_t len;
   int i,j;
   int  nrow,ncol;
   int padded_nrow;
   int size;
   float f;
   float *M;

   if ((fi = fopen(filename,"r")) == NULL) {
      fprintf(stderr,"Cannot open file %s\n",filename);
      exit(1);
   }
   // Determine the number of column from the first line.
   //fscanf(fi,"%d %d",&nrow,&ncol);
   line = NULL;
   if ((len = getline(&line,&bufsize,fi)) < 0) {
      fprintf(stderr,"Cannot read a line in %s\n",filename); 
      exit(1);
   }
   ncol = 0;
   str = line;
   while ((word = (char *) strtok(str,delim)) != NULL) {
      ncol++;
      str = NULL;
   }
   rewind(fi);
   free(line);
    
   nrow = 0;
   while(!fscanf(fi,"%*[^\n]%*c")) {
      nrow++;
   }
   rewind(fi);

//   padded_nrow = ((int) ((((float) nrow) + padding_size)/padding_size))*padding_size;
   padded_nrow = ((nrow + padding_size - 1)/padding_size)*padding_size;
   size = padded_nrow*ncol*sizeof(float);
    
   M = (float *) malloc(size);
   if (M == NULL) {
      fprintf(stderr,"Cannot allocate memory of size %d\n",size);
      exit(1);
   }

   size = 0;
   for (i=0; i < nrow; i++) {
      for (j=0; j < ncol; j++) {
         fscanf(fi,"%f",&f);
         M[i*ncol + j] = f;
         size++;
      }
   }
   if (size != nrow*ncol) {
      fprintf(stderr,"# of read elements != %d\n",nrow*ncol);
      exit(1);
   }
   
   fclose(fi);

   *row = nrow; *col = ncol; *padded_row = padded_nrow;
   fprintf(stderr,"# of read elements = %dx%d into %dx%d\n",nrow,ncol,padded_nrow,ncol);
   return M;
}

/*
 * Print a submatrix to stdout
 * @param M The array representing a matrix (input)
 * @param row Number of rows (input)
 * @param col Number of columns (input)
 * @param subrow Number of visible rows (input)
 * @param subcol Number of visible columns (input)
 */
void write_submatrix(float *M,int row, int col,int subrow, int subcol) {
   int i,j;

   for (i=0; i < subrow; i++) {
      for (j=0; j < subcol; j++) {
         printf("%.3f ",M[i*col + j]);
      }
      printf("\n");
   }
}

/*
 * Print an entire matrix to stdout
 * @param M The array representing a matrix (input)
 * @param row Number of rows (input)
 * @param col Number of columns (input)
 */
void write_matrix(float *M,int row, int col) {
   int i,j;

   for (i=0; i < row; i++) {
      for (j=0; j < col; j++) {
         printf("%.3f ",M[i*col + j]);
      }
      printf("\n");
   }
}

